<?php

class File
{
	// private static member
	private static $headerStripped;
	
	// public static member
	public static $header;
	
	// constant members
	const FILENAME_MAX_LENGTH	= 128;
	const DEFAULT_FILENAME		= 'temp.txt';
	const GET		= 0;
	const POST		= 1;
	const CUSTOM	= 2;
	
	/**************************** public static methods ***************************/
	public static function error($message)
	{
		throw new Exception($message);
	}
	
	public static function setRealpath(&$path)
	{
		$path = self::getRealpath($path);
	}
	
	public static function getRealpath($path)
	{
		if (!file_exists($path))
			self::error("File '".$path."' doesn't exist.");
		
		$realpath = realpath($path);
		
		if (!$realpath)
			self::error("Can not set realpath '".$path."'.");
		
		return str_replace('//', '/', str_replace('\\', '/', $realpath).(is_dir($path) ? '/' : ''));
	}
	
	public static function getFilesByPattern($path, $pattern, $ignoreDirectories = true)
	{
		$path	= self::getRealpath($path);
		$dir	= dir($path);
		
		while (($entry = $dir->read()) !== false)
		{
			if ($entry == '.' || $entry == '..') continue;
			if ($ignoreDirectories && is_dir($path.$entry)) continue;
			if (preg_match($pattern, $entry)) $r[] = $entry;
		}
		
		return isset($r) ? $r : null;
	}
	
	public static function truncateDirectory($path, $truncateSubDirectory = true)
	{
		$path	= self::getRealpath($path);
		$dir	= dir($path);
		
		while (($entry = $dir->read()) !== false)
		{
			if ($entry == '.' || $entry == '..') continue;
			
			if (is_dir($path.$entry))
			{
				if (!$truncateSubDirectory) continue;
				
				self::truncateDirectory($path.$entry);
				rmdir($path.$entry);
			}
			else unlink($path.$entry);
		}
	}

	public static function serializeToFile($object, $fileName = self::DEFAULT_FILENAME)
	{
		self::saveFile(serialize($object), $fileName);
	}
	
	public static function unserializeFromFile($fileName = self::DEFAULT_FILENAME, $failedReturn = array())
	{
		if (!file_exists($fileName)) return $failedReturn;
		return unserialize(self::getFile($fileName));
	}
	
    public static function saveFile($data, $fileName = self::DEFAULT_FILENAME, $mode = 'w') 
    {
        $fp = fopen($fileName, $mode);
        if (!$fp) self::error("Can not open file '".$fileName."'.");
        if ($mode != 'r') flock($fp, LOCK_EX);
        fwrite($fp, $data);
        fclose($fp);
    }
    
    public static function appendFile($data, $fileName = self::DEFAULT_FILENAME)
    {
    	self::saveFile($data, $fileName, 'a');
    }

    public static function gzencode($data)
    {
    	return gzencode($data, 9);
    }

    public static function gzdecode($data)
    {
    	if (!self::isGzipped($data)) return $data;
    	return gzinflate(substr($data, 10));
    }

    public static function isGzipped($data)
    {
    	if (strlen($data) < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) return false;
    	return true;
    }
  
    public static function getGzippedFile($fileName)
    {
    	return self::gzencode(self::getFile($fileName));
    }
    
    public static function getUngzippedFile($fileName)
    {
    	return self::gzdecode(self::getFile($fileName));
    }

    public static function downloadGzippedFile($fileName)
    {
    	$data = self::getGzippedFile($fileName);
    	self::downloadFile($data, basename($fileName).'.gz', 'application/x-gzip');
    }

    public static function downloadFile($data = null, $fileName = self::DEFAULT_FILENAME, $mimeType = 'text/plain') 
    {
    	if ($data === null)
    		$data = self::getFile($fileName);
    	
        header('Content-Type: '.$mimeType);
        header('Content-Disposition: attachment; filename="'.$fileName.'"');
        header('Content-Length: '.strlen($data));
        header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');

        echo $data;
    }
	
	public static function getDisplaySize($size)
	{
		$units = array('B', 'KB', 'MB', 'GB', 'TB');
		$i = 0;
		
		while ($intSize = intval($size / 1024))
		{
			$oldSize = $size;
			$size = $intSize;
			$i++;
		}
		
		if ($i)
			$size = $size.'.'.substr(intval($oldSize * 10 / 1024), -1);
		
		return $size.' '.$units[$i];
	}
	
    public static function getFile($filename = self::DEFAULT_FILENAME, $outputDirectly = false, $lineLimit = -1) 
    {                  
        $fp = fopen($filename, 'r');
        if (!$fp) self::error("Can not open file '".$filename."'.");
        
     	$r = '';
        $i = 0;

        while (!feof($fp) && ($lineLimit == -1 || $i < $lineLimit)) 
        {
            if ($outputDirectly) echo fgets($fp);
            else $r .= fgets($fp);
            
            $i++;
        }

        fclose($fp);        
        return $r;
    }
}
